package com.luoqiwen.android.sinaurldecoder

import android.widget.Toast
import com.squareup.okhttp.HttpUrl
import com.squareup.okhttp.OkHttpClient
import com.squareup.okhttp.Request
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.concurrent.TimeUnit

object URLDecoder {
        private val main = MainActivity.INSTANCE
    private val internetErrHandler = CoroutineExceptionHandler { _, throwable ->
        main.debug("   Error encountered : ${throwable.localizedMessage}")
    }
        suspend fun decode(input: String, secondaryDecode: Boolean, secondaryDecodeDepth : Int = 0) : MutableMap<String, MutableSet<HttpUrl>> {
            main.debug("URLDecoder: Decode task started: input=$input")

            val result = mutableMapOf<String, MutableSet<HttpUrl>>()
            val inputURL = HttpUrl.parse(input)
            if (inputURL == null) {
                Toast.makeText(main.applicationContext, "输个url好不好呀", Toast.LENGTH_SHORT).show()
                return result
            }

            inputURL.queryParameterNames().forEach { name->
                main.debug("Input url parsed. Analyzing param values under key=$name:")
                inputURL.queryParameterValues(name).forEach { value->
                    main.debug(" - Now analyzing value=$value")
                    var parse = HttpUrl.parse(value)
                    if (parse != null) {
                        main.debug("   Value parsed as http url.")
                        if (secondaryDecode) {
                            var new : HttpUrl? = null
                            main.debug("   Working on secondary decode task. Depth: $secondaryDecodeDepth")
                            for ( i in 0 until secondaryDecodeDepth) {
                                if (new != null && new == parse)
                                    break

                                new = secondaryDecode(parse)

                                if (new == parse)
                                    break
                                else
                                    parse = new
                            }
                        }
                        main.debug("   Value=$value eventually parsed as httpurl=$parse")
                        if (!result.containsKey(name))
                            result[name] = mutableSetOf()
                        result[name]?.add(parse)
                    }
                }
            }

            return result
        }

        private val Client = OkHttpClient()
        init {
            Client.setReadTimeout(3, TimeUnit.SECONDS)
            Client.setConnectTimeout(2, TimeUnit.SECONDS)
            Client.followRedirects = false
            Client.followSslRedirects = false
        }

        private suspend fun secondaryDecode(input: HttpUrl): HttpUrl {
            main.debug("   Using okhttp for secondary decode.")
            main.debug("   Requesting server host: ${input.host()}, input_url=$input")
            val req = Request.Builder().get().url(input).build()
            val rep = withContext(Dispatchers.IO + internetErrHandler) {
                Client.newCall(req).execute()
            }
            main.debug("   Response from ${input.host()} received. Now parsing header for key 'Location'")
            return HttpUrl.parse(rep?.header("Location", "")) ?: input
        }

}